#!/bin/bash
###############################################################################
#       脚本名称: log_config.sh
#       功能描述: 配置管理模块,负责加载、解析、验证和缓存日志配置。
#       作者: 林再来
#       日期: 2025-10-14
#       版本: 1.0
#       功能:
#           1、加载YAML配置文件(使用yq)
#           2、配置验证和默认值处理
#           3、配置缓存到关联数组
#           4、提供配置查询接口
#       依赖(插件/命令):
#           yq(YAML解析)
###############################################################################

# 防止重复加载
[[ -n "${_LOG_CONFIG_LOADED:-}" ]] && return 0
readonly _LOG_CONFIG_LOADED=1

# 加载依赖模块
_LOG_CONFIG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${_LOG_CONFIG_DIR}/log_level.sh"

# 获取项目根目录
PROJECT_ROOT="$(cd "${_LOG_CONFIG_DIR}/../../.." && pwd)"

#-----------------------------------------------------------------------------
# 全局变量
#-----------------------------------------------------------------------------
# 配置缓存
declare -gA _LOG_CONFIG_CACHE
# 配置文件路径
declare -g _LOG_CONFIG_FILE=""
# 是否已初始化
declare -g _LOG_CONFIG_INITIALIZED="false"

#-----------------------------------------------------------------------------
# 默认配置（参考config模块的做法，先检查是否已定义）
#-----------------------------------------------------------------------------
if [[ -z "${DEFAULT_LOG_LEVEL:-}" ]]; then
    readonly DEFAULT_LOG_LEVEL="INFO"
fi
if [[ -z "${DEFAULT_ASYNC:-}" ]]; then
    readonly DEFAULT_ASYNC="false"
fi
# DEFAULT_BUFFER_SIZE 已在 log_buffer.sh 中定义
if [[ -z "${DEFAULT_SANITIZE:-}" ]]; then
    readonly DEFAULT_SANITIZE="false"
fi

#-----------------------------------------------------------------------------
# 函数: 初始化配置管理
# 参数: $1 - 配置文件路径
# 返回: 0-成功, 1-失败
#-----------------------------------------------------------------------------
function log_config_init() {
    local config_file="$1"
    
    # 验证配置文件
    if [[ -z "$config_file" ]]; then
        echo "错误: 配置文件路径不能为空" >&2
        return 1
    fi
    
    if [[ ! -f "$config_file" ]]; then
        echo "错误: 配置文件不存在: $config_file" >&2
        return 1
    fi
    
    _LOG_CONFIG_FILE="$config_file"
    
    # 加载配置
    if ! _log_config_parse "$config_file"; then
        echo "错误: 配置文件解析失败: $config_file" >&2
        return 1
    fi
    
    # 验证配置
    if ! _log_config_validate; then
        echo "错误: 配置验证失败" >&2
        return 1
    fi
    
    _LOG_CONFIG_INITIALIZED="true"
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 解析配置文件
# 参数: $1 - 配置文件路径
# 返回: 0-成功, 1-失败
#-----------------------------------------------------------------------------
function _log_config_parse() {
    local config_file="$1"
    
    # 初始化yq（如果尚未初始化）
    if [[ -z "${yq_binary:-}" ]]; then
        # 简单的yq初始化逻辑（不依赖logger）
        if command -v yq &>/dev/null; then
            yq_binary="yq"
        else
            # 尝试使用项目内置yq
            local arch=""
            case "$(uname -m)" in
                x86_64|amd64) arch="amd64" ;;
                aarch64|arm64) arch="arm64" ;;
                *) arch="amd64" ;;
            esac
            local yq_path="${PROJECT_ROOT}/packages/yq/v4.35.1/${arch}/yq_linux_v4.35.1"
            if [[ -f "$yq_path" ]]; then
                chmod +x "$yq_path" 2>/dev/null
                yq_binary="$yq_path"
            fi
        fi
    fi
    
    # 检查yq是否可用
    if [[ -z "${yq_binary:-}" ]] || ! command -v "$yq_binary" &>/dev/null; then
        echo "错误: yq命令不可用,无法解析YAML配置" >&2
        return 1
    fi
    
    # 读取全局配置
    local global_level=$("$yq_binary" eval '.logger.global.level // ""' "$config_file" 2>/dev/null)
    local global_async=$("$yq_binary" eval '.logger.global.async // ""' "$config_file" 2>/dev/null)
    local global_buffer=$("$yq_binary" eval '.logger.global.buffer_size // ""' "$config_file" 2>/dev/null)
    local global_sanitize=$("$yq_binary" eval '.logger.global.sanitize // ""' "$config_file" 2>/dev/null)
    
    # 使用默认值(如果配置不存在)
    _LOG_CONFIG_CACHE["global.level"]="${global_level:-$DEFAULT_LOG_LEVEL}"
    _LOG_CONFIG_CACHE["global.async"]="${global_async:-$DEFAULT_ASYNC}"
    _LOG_CONFIG_CACHE["global.buffer_size"]="${global_buffer:-$DEFAULT_BUFFER_SIZE}"
    _LOG_CONFIG_CACHE["global.sanitize"]="${global_sanitize:-$DEFAULT_SANITIZE}"
    
    # 读取appender配置
    local appender_count=$("$yq_binary" eval '.logger.appenders | length' "$config_file" 2>/dev/null)
    appender_count="${appender_count:-0}"
    
    _LOG_CONFIG_CACHE["appenders.count"]="$appender_count"
    
    # 遍历所有appender
    for ((i=0; i<appender_count; i++)); do
        local name=$("$yq_binary" eval ".logger.appenders[$i].name" "$config_file" 2>/dev/null)
        local type=$("$yq_binary" eval ".logger.appenders[$i].type" "$config_file" 2>/dev/null)
        local level=$("$yq_binary" eval ".logger.appenders[$i].level // \"\"" "$config_file" 2>/dev/null)
        local formatter=$("$yq_binary" eval ".logger.appenders[$i].formatter // \"\"" "$config_file" 2>/dev/null)
        local enabled=$("$yq_binary" eval ".logger.appenders[$i].enabled // \"\"" "$config_file" 2>/dev/null)
        
        # 存储appender配置
        _LOG_CONFIG_CACHE["appender.$i.name"]="$name"
        _LOG_CONFIG_CACHE["appender.$i.type"]="$type"
        _LOG_CONFIG_CACHE["appender.$i.level"]="${level:-${_LOG_CONFIG_CACHE[global.level]}}"
        _LOG_CONFIG_CACHE["appender.$i.formatter"]="${formatter:-plain}"
        _LOG_CONFIG_CACHE["appender.$i.enabled"]="${enabled:-true}"
        
        # 根据type读取特定配置
        case "$type" in
            console)
                local color=$("$yq_binary" eval ".logger.appenders[$i].color // \"\"" "$config_file" 2>/dev/null)
                local target=$("$yq_binary" eval ".logger.appenders[$i].target // \"\"" "$config_file" 2>/dev/null)
                _LOG_CONFIG_CACHE["appender.$i.color"]="${color:-auto}"
                _LOG_CONFIG_CACHE["appender.$i.target"]="${target:-stdout}"
                ;;
            file)
                local file=$("$yq_binary" eval ".logger.appenders[$i].file // \"\"" "$config_file" 2>/dev/null)
                local max_size=$("$yq_binary" eval ".logger.appenders[$i].rotation.max_size // \"\"" "$config_file" 2>/dev/null)
                local max_files=$("$yq_binary" eval ".logger.appenders[$i].rotation.max_files // \"\"" "$config_file" 2>/dev/null)
                local strategy=$("$yq_binary" eval ".logger.appenders[$i].rotation.strategy // \"\"" "$config_file" 2>/dev/null)
                local compress=$("$yq_binary" eval ".logger.appenders[$i].rotation.compress // \"\"" "$config_file" 2>/dev/null)
                
                _LOG_CONFIG_CACHE["appender.$i.file"]="${file:-logs/app/app.log}"
                _LOG_CONFIG_CACHE["appender.$i.max_size"]="${max_size:-100M}"
                _LOG_CONFIG_CACHE["appender.$i.max_files"]="${max_files:-10}"
                _LOG_CONFIG_CACHE["appender.$i.rotation_strategy"]="${strategy:-size}"
                _LOG_CONFIG_CACHE["appender.$i.compress"]="${compress:-false}"
                ;;
        esac
    done
    
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 验证配置
# 返回: 0-有效, 1-无效
#-----------------------------------------------------------------------------
function _log_config_validate() {
    # 验证全局日志级别
    local global_level="${_LOG_CONFIG_CACHE[global.level]}"
    if ! _log_level_is_valid "$global_level"; then
        echo "错误: 无效的日志级别: $global_level" >&2
        return 1
    fi
    
    # 验证async配置
    local async="${_LOG_CONFIG_CACHE[global.async]}"
    if [[ ! "$async" =~ ^(true|false)$ ]]; then
        echo "错误: global.async必须是true或false" >&2
        return 1
    fi
    
    # 验证buffer_size
    local buffer_size="${_LOG_CONFIG_CACHE[global.buffer_size]}"
    if [[ ! "$buffer_size" =~ ^[0-9]+$ ]]; then
        echo "错误: global.buffer_size必须是数字" >&2
        return 1
    fi
    
    # 验证appender配置
    local appender_count="${_LOG_CONFIG_CACHE[appenders.count]}"
    if [[ $appender_count -eq 0 ]]; then
        echo "警告: 没有配置任何appender,将使用默认控制台输出" >&2
    fi
    
    # 验证每个appender
    for ((i=0; i<appender_count; i++)); do
        local name="${_LOG_CONFIG_CACHE[appender.$i.name]}"
        local type="${_LOG_CONFIG_CACHE[appender.$i.type]}"
        local level="${_LOG_CONFIG_CACHE[appender.$i.level]}"
        
        # 验证必填字段
        if [[ -z "$name" ]]; then
            echo "错误: appender[$i]缺少name字段" >&2
            return 1
        fi
        
        if [[ -z "$type" ]]; then
            echo "错误: appender[$i]缺少type字段" >&2
            return 1
        fi
        
        # 验证type
        if [[ ! "$type" =~ ^(console|file|json)$ ]]; then
            echo "警告: appender[$i]的type '$type' 未实现,将被忽略" >&2
        fi
        
        # 验证level
        if ! _log_level_is_valid "$level"; then
            echo "错误: appender[$i]的日志级别无效: $level" >&2
            return 1
        fi
    done
    
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 获取配置值
# 参数: $1 - 配置键(如: global.level, appender.0.name)
#       $2 - 默认值(可选)
# 返回: 输出配置值,不存在则返回默认值
#-----------------------------------------------------------------------------
function log_config_get() {
    local key="$1"
    local default_value="${2:-}"
    
    if [[ -n "${_LOG_CONFIG_CACHE[$key]:-}" ]]; then
        echo "${_LOG_CONFIG_CACHE[$key]}"
    else
        echo "$default_value"
    fi
}

#-----------------------------------------------------------------------------
# 函数: 检查配置是否已初始化
# 返回: 0-已初始化, 1-未初始化
#-----------------------------------------------------------------------------
function log_config_is_initialized() {
    [[ "$_LOG_CONFIG_INITIALIZED" == "true" ]]
}

#-----------------------------------------------------------------------------
# 函数: 获取所有启用的appender
# 返回: 输出appender索引列表(空格分隔)
#-----------------------------------------------------------------------------
function log_config_get_enabled_appenders() {
    local appender_count="${_LOG_CONFIG_CACHE[appenders.count]:-0}"
    local enabled_list=""
    
    for ((i=0; i<appender_count; i++)); do
        local enabled="${_LOG_CONFIG_CACHE[appender.$i.enabled]:-true}"
        if [[ "$enabled" == "true" ]]; then
            enabled_list+="$i "
        fi
    done
    
    echo "${enabled_list% }"  # 移除末尾空格
}

#-----------------------------------------------------------------------------
# 函数: 重新加载配置
# 返回: 0-成功, 1-失败
#-----------------------------------------------------------------------------
function log_config_reload() {
    if [[ -z "$_LOG_CONFIG_FILE" ]]; then
        echo "错误: 配置未初始化,无法重新加载" >&2
        return 1
    fi
    
    # 清空缓存
    _LOG_CONFIG_CACHE=()
    
    # 重新加载
    log_config_init "$_LOG_CONFIG_FILE"
}

#-----------------------------------------------------------------------------
# 函数: 打印当前配置(用于调试)
# 返回: 无
#-----------------------------------------------------------------------------
function log_config_dump() {
    echo "=== 日志配置信息 ==="
    echo ""
    echo "配置文件: $_LOG_CONFIG_FILE"
    echo "初始化状态: $_LOG_CONFIG_INITIALIZED"
    echo ""
    echo "全局配置:"
    echo "  level: ${_LOG_CONFIG_CACHE[global.level]}"
    echo "  async: ${_LOG_CONFIG_CACHE[global.async]}"
    echo "  buffer_size: ${_LOG_CONFIG_CACHE[global.buffer_size]}"
    echo "  sanitize: ${_LOG_CONFIG_CACHE[global.sanitize]}"
    echo ""
    
    local appender_count="${_LOG_CONFIG_CACHE[appenders.count]:-0}"
    echo "Appenders配置(共$appender_count个):"
    for ((i=0; i<appender_count; i++)); do
        echo "  [$i] ${_LOG_CONFIG_CACHE[appender.$i.name]} (${_LOG_CONFIG_CACHE[appender.$i.type]})"
        echo "      level: ${_LOG_CONFIG_CACHE[appender.$i.level]}"
        echo "      formatter: ${_LOG_CONFIG_CACHE[appender.$i.formatter]}"
        echo "      enabled: ${_LOG_CONFIG_CACHE[appender.$i.enabled]}"
        
        local type="${_LOG_CONFIG_CACHE[appender.$i.type]}"
        if [[ "$type" == "file" ]]; then
            echo "      file: ${_LOG_CONFIG_CACHE[appender.$i.file]}"
            echo "      rotation: ${_LOG_CONFIG_CACHE[appender.$i.rotation_strategy]}, max_size=${_LOG_CONFIG_CACHE[appender.$i.max_size]}, max_files=${_LOG_CONFIG_CACHE[appender.$i.max_files]}"
        elif [[ "$type" == "console" ]]; then
            echo "      color: ${_LOG_CONFIG_CACHE[appender.$i.color]}"
            echo "      target: ${_LOG_CONFIG_CACHE[appender.$i.target]}"
        fi
        echo ""
    done
}

#-----------------------------------------------------------------------------
# 测试函数
#-----------------------------------------------------------------------------
function _log_config_test() {
    echo "=== 配置管理模块测试 ==="
    
    # 查找配置文件
    local test_config="${PROJECT_ROOT}/config/base/logger.yaml"
    
    if [[ ! -f "$test_config" ]]; then
        echo "警告: 测试配置文件不存在: $test_config"
        echo "跳过测试"
        return 0
    fi
    
    echo ""
    echo "1. 初始化配置:"
    if log_config_init "$test_config"; then
        echo "  ✓ 配置初始化成功"
    else
        echo "  ✗ 配置初始化失败"
        return 1
    fi
    
    echo ""
    echo "2. 获取配置值:"
    echo "  global.level = $(log_config_get 'global.level')"
    echo "  global.async = $(log_config_get 'global.async')"
    echo "  appender.0.name = $(log_config_get 'appender.0.name')"
    echo "  appender.0.type = $(log_config_get 'appender.0.type')"
    
    echo ""
    echo "3. 启用的appenders:"
    echo "  $(log_config_get_enabled_appenders)"
    
    echo ""
    echo "4. 完整配置信息:"
    log_config_dump
}

# 如果直接执行此脚本,运行测试
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    _log_config_test
fi

